﻿/*********************************************************************
 ****  描    述： <常用数据类型大小端互转扩展方法>
 ****  创 建 者： <周渊>
 ****  创建时间： <2014-3-27>
 ****  修改时间： < >
 ****  修改标识:
 *     修改人    
 *     修改日期  
 *     修改内容 :  
*********************************************************************/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace System
{
    /// <summary>
    /// 常用数据类型大小端互转扩展方法
    /// </summary>
    public static class SwapEndian
    {
        /// <summary>
        /// 大小端互转
        /// </summary>
        /// <param name="n"></param>
        /// <returns></returns>
        public static short SwapInt16(this short n)
        {
            return (short)(((n & 0xff) << 8) | ((n >> 8) & 0xff));
        }
        /// <summary>
        /// 大小端互转
        /// </summary>
        /// <param name="n"></param>
        /// <returns></returns>
        public static ushort SwapUInt16(this ushort n)
        {
            return (ushort)(((n & 0xff) << 8) | ((n >> 8) & 0xff));
        }
        /// <summary>
        /// 大小端互转
        /// </summary>
        /// <param name="n"></param>
        /// <returns></returns>
        public static int SwapInt32(this int n)
        {
            return (int)(((SwapInt16((short)n) & 0xffff) << 0x10) |
                          (SwapInt16((short)(n >> 0x10)) & 0xffff));
        }
        /// <summary>
        /// 大小端互转
        /// </summary>
        /// <param name="n"></param>
        /// <returns></returns>
        public static uint SwapUInt32(this uint n)
        {
            return (uint)(((SwapUInt16((ushort)n) & 0xffff) << 0x10) |
                           (SwapUInt16((ushort)(n >> 0x10)) & 0xffff));
        }
        /// <summary>
        /// 大小端互转
        /// </summary>
        /// <param name="n"></param>
        /// <returns></returns>
        public static long SwapInt64(this long n)
        {
            return (long)(((SwapInt32((int)n) & 0xffffffffL) << 0x20) |
                           (SwapInt32((int)(n >> 0x20)) & 0xffffffffL));
        }
        /// <summary>
        /// 大小端互转
        /// </summary>
        /// <param name="n"></param>
        /// <returns></returns>
        public static ulong SwapUInt64(this ulong n)
        {
            return (ulong)(((SwapUInt32((uint)n) & 0xffffffffL) << 0x20) |
                            (SwapUInt32((uint)(n >> 0x20)) & 0xffffffffL));
        }
        #region double,float 不进行大小端转换
        ///// <summary>
        ///// double 数据互转
        ///// </summary>
        ///// <param name="n"></param>
        ///// <returns></returns>
        //public static unsafe double SwapDouble(this double n)
        //{
        //    byte[] buffer = new byte[8];
        //    byte* p = (byte*)&n;
        //    buffer[0] = p[4];
        //    buffer[1] = p[5];
        //    buffer[2] = p[6];
        //    buffer[3] = p[7];
        //    buffer[4] = p[0];
        //    buffer[5] = p[1];
        //    buffer[6] = p[2];
        //    buffer[7] = p[3];
        //    return BitConverter.ToSingle(buffer, 0);
        //}


        ///// <summary>
        ///// float进行转换大小端
        ///// </summary>
        ///// <param name="n"></param>
        ///// <returns></returns>
        //public static unsafe float SwapFloat(this Single n)
        //{
        //    byte[] buffer = new byte[4];
        //    byte* numRef = ((byte*)&n);
        //    buffer[0] = numRef[3];
        //    buffer[1] = numRef[2];
        //    buffer[2] = numRef[1];
        //    buffer[3] = numRef[0];
        //    //    return *(((float*)&runRef));
        //    return BitConverter.ToSingle(buffer, 0);
        //}
        #endregion




#if BIGEndia 
        /// <summary>
        /// 传入int返回byte数组
        /// </summary>
        /// <param name="value"></param>
        /// <returns></returns>
        public static unsafe byte[] GetBytes(this int value)
        {
            byte[] buffer = new byte[4];
            fixed (byte* numRef = buffer)
            {
                *((int*)numRef) = value;
            }
            return buffer;
        }
        /// <summary>
        /// 将int转换成为大端
        /// </summary>
        /// <param name="value"></param>
        /// <param name="startIndex"></param>
        /// <returns></returns>
        public static unsafe int ToInt32BigEndian(byte[] value, int startIndex)
        {
            if (startIndex >= value.Length)
            {
                DebugCheck.ThrowIfTrue(startIndex <= value.Length, "索引超出范围");
            }
            if (startIndex > (value.Length - 4))
            {
                DebugCheck.ThrowIfTrue(startIndex <= value.Length, "开始索引没有足够多的范围,读取4字节的int");
            }
            fixed (byte* numRef = &(value[startIndex]))
            {
                //if ((startIndex % 4) == 0)
                //{
                //    return *(((int*)numRef));
                //}
                //if (IsLittleEndian)
                //{
                //    return (((numRef[0] | (numRef[1] << 8)) | (numRef[2] << 0x10)) | (numRef[3] << 0x18));
                //}
                return ((((numRef[0] << 0x18) | (numRef[1] << 0x10)) | (numRef[2] << 8)) | numRef[3]);
            }
        }

#endif

    }
}
